<template>
  <div class="app-container">
    <el-card>
      <!-- 搜索区域 -->
      <div class="search-container" v-show="showSearch">
        <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
          <el-form-item label="产品名称" prop="productName">
            <el-input
              v-model="queryParams.productName"
              placeholder="请输入产品名称"
              clearable
              style="width: 240px"
              @keyup.enter="handleQuery"
            />
          </el-form-item>
          <el-form-item label="产品编码" prop="productCode">
            <el-input
              v-model="queryParams.productCode"
              placeholder="请输入产品编码"
              clearable
              style="width: 240px"
              @keyup.enter="handleQuery"
            />
          </el-form-item>
          <el-form-item label="产品分类" prop="categoryId">
            <el-tree-select
              v-model="queryParams.categoryId"
              :data="categoryOptions"
              :props="{ value: 'categoryId', label: 'categoryName', children: 'children' }"
              value-key="categoryId"
              placeholder="请选择产品分类"
              check-strictly
              clearable
              style="width: 240px"
            />
          </el-form-item>
          <el-form-item label="设备类型" prop="deviceType">
            <el-select v-model="queryParams.deviceType" placeholder="请选择设备类型" clearable style="width: 240px">
              <el-option
                v-for="dict in deviceTypeOptions"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="产品状态" prop="status">
            <el-select v-model="queryParams.status" placeholder="请选择产品状态" clearable style="width: 240px">
              <el-option label="正常" value="0" />
              <el-option label="停用" value="1" />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
          </el-form-item>
        </el-form>
      </div>

      <!-- 操作按钮 -->
      <el-row :gutter="10" class="mb8">
        <el-col :span="1.5">
          <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['iot:product:add']">新增</el-button>
        </el-col>
        <el-col :span="1.5">
          <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['iot:product:edit']">修改</el-button>
        </el-col>
        <el-col :span="1.5">
          <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['iot:product:remove']">删除</el-button>
        </el-col>
        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
      </el-row>

      <!-- 产品列表 -->
      <el-table v-loading="loading" :data="productList" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="产品ID" align="center" prop="productId" width="80" />
        <el-table-column label="产品名称" align="center" prop="productName" :show-overflow-tooltip="true" />
        <el-table-column label="产品编码" align="center" prop="productCode" width="120" />
        <el-table-column label="产品分类" align="center" prop="categoryName" width="120" />
        <el-table-column label="设备类型" align="center" prop="deviceType" width="120">
          <template #default="scope">
            <dict-tag :options="deviceTypeOptions" :value="scope.row.deviceType" />
          </template>
        </el-table-column>
        <el-table-column label="产品型号" align="center" prop="productModel" width="120" />
        <el-table-column label="产品品牌" align="center" prop="brand" width="100" />
        <el-table-column label="通信协议" align="center" prop="protocolType" width="120" />
        <el-table-column label="产品价格" align="center" prop="price" width="100">
          <template #default="scope">
            <span v-if="scope.row.price">¥{{ scope.row.price }}</span>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="产品状态" align="center" prop="status" width="100">
          <template #default="scope">
            <el-tag v-if="scope.row.status === '0'" type="success">正常</el-tag>
            <el-tag v-else-if="scope.row.status === '1'" type="danger">停用</el-tag>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="创建时间" align="center" prop="createTime" width="180">
          <template #default="scope">
            <span>{{ parseTime(scope.row.createTime) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
          <template #default="scope">
            <el-button link type="primary" icon="View" @click="handleView(scope.row)" v-hasPermi="['iot:product:query']">查看</el-button>
            <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['iot:product:edit']">修改</el-button>
            <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['iot:product:remove']">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <pagination
        v-show="total > 0"
        :total="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        @pagination="getList"
      />
    </el-card>

    <!-- 产品表单对话框 -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="800px" append-to-body @close="closeDialog">
      <el-form ref="productFormRef" :model="form" :rules="rules" label-width="100px">
        <el-tabs v-model="productFormTab">
          <el-tab-pane label="基本信息" name="basic">
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="产品名称" prop="productName">
                  <el-input v-model="form.productName" placeholder="请输入产品名称" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="产品编码" prop="productCode">
                  <el-input v-model="form.productCode" placeholder="请输入产品编码" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="产品分类" prop="categoryId">
                  <el-tree-select
                    v-model="form.categoryId"
                    :data="categoryOptions"
                    :props="{ value: 'categoryId', label: 'categoryName', children: 'children' }"
                    value-key="categoryId"
                    placeholder="请选择产品分类"
                    check-strictly
                  />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="设备类型" prop="deviceType">
                  <el-select v-model="form.deviceType" placeholder="请选择设备类型" style="width: 100%">
                    <el-option
                      v-for="dict in deviceTypeOptions"
                      :key="dict.value"
                      :label="dict.label"
                      :value="dict.value"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="产品型号" prop="productModel">
                  <el-input v-model="form.productModel" placeholder="请输入产品型号" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="产品品牌" prop="brand">
                  <el-input v-model="form.brand" placeholder="请输入产品品牌" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="产品规格" prop="specification">
                  <el-input v-model="form.specification" placeholder="请输入产品规格" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="数据格式" prop="dataFormat">
                  <el-input v-model="form.dataFormat" placeholder="请输入数据格式" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="工作电压" prop="workingVoltage">
                  <el-input v-model="form.workingVoltage" placeholder="请输入工作电压" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="工作温度" prop="workingTemperature">
                  <el-input v-model="form.workingTemperature" placeholder="请输入工作温度" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="防护等级" prop="protectionLevel">
                  <el-input v-model="form.protectionLevel" placeholder="请输入防护等级" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="产品价格" prop="price">
                  <el-input-number v-model="form.price" :precision="2" :min="0" placeholder="请输入产品价格" style="width: 100%" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="供应商" prop="supplier">
                  <el-input v-model="form.supplier" placeholder="请输入供应商" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="供应商联系方式" prop="supplierContact">
                  <el-input v-model="form.supplierContact" placeholder="请输入供应商联系方式" />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="产品状态" prop="status">
                  <el-radio-group v-model="form.status">
                    <el-radio label="0">正常</el-radio>
                    <el-radio label="1">停用</el-radio>
                  </el-radio-group>
                </el-form-item>
              </el-col>
              <el-col :span="24">
                <el-form-item label="产品描述" prop="description">
                  <el-input v-model="form.description" type="textarea" placeholder="请输入产品描述" />
                </el-form-item>
              </el-col>
              <el-col :span="24">
                <el-form-item label="技术参数" prop="technicalParams">
                  <el-input v-model="form.technicalParams" type="textarea" placeholder="请输入技术参数" />
                </el-form-item>
              </el-col>
            </el-row>
          </el-tab-pane>
          <el-tab-pane label="通信方式" name="protocol">
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="通信协议" prop="protocolType">
                  <el-select v-model="form.protocolType" placeholder="请选择通信协议" style="width: 100%">
                    <el-option label="MQTT" value="mqtt" />
                    <el-option label="TCP" value="tcp" />
                    <el-option label="Modbus" value="modbus" />
                    <el-option label="HTTP" value="http" />
                    <el-option label="CoAP" value="coap" />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="绑定规则" prop="flowId">
                  <el-input
                    v-model="selectedFlowName"
                    placeholder="请选择规则"
                    readonly
                    @click="openFlowSelector"
                    style="cursor: pointer"
                  >
                    <template #suffix>
                      <el-icon><Search /></el-icon>
                    </template>
                  </el-input>
                </el-form-item>
              </el-col>
              <el-col :span="24" v-if="form.protocolType">
                <el-form-item label="协议配置(JSON)" prop="protocolConfig">
                  <div style="display:flex; gap:8px; width:100%">
                    <el-input
                      v-model="form.protocolConfig"
                      type="textarea"
                      :rows="6"
                      :placeholder="protocolJsonPlaceholder"
                    />
                    <el-button type="primary" @click="openProtoEditor">编辑</el-button>
                  </div>
                </el-form-item>
              </el-col>
            </el-row>
          </el-tab-pane>
        </el-tabs>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 协议参数编辑对话框（产品） -->
    <el-dialog v-model="protoEditor.visible" title="编辑协议参数" width="700px" append-to-body>
      <template v-if="form.protocolType === 'mqtt'">
        <el-form label-width="120px">
          <el-form-item label="Broker URL">
            <el-input v-model="protoEditor.mqtt.brokerUrl" placeholder="例如: mqtt://127.0.0.1:1883" />
          </el-form-item>
          <el-form-item label="Client ID">
            <el-input v-model="protoEditor.mqtt.clientId" />
          </el-form-item>
          <el-form-item label="用户名">
            <el-input v-model="protoEditor.mqtt.username" />
          </el-form-item>
          <el-form-item label="密码">
            <el-input v-model="protoEditor.mqtt.password" type="password" />
          </el-form-item>
          <el-form-item label="发布主题">
            <el-input v-model="protoEditor.mqtt.publishTopic" />
          </el-form-item>
          <el-form-item label="订阅主题">
            <el-input v-model="protoEditor.mqtt.subscribeTopic" />
          </el-form-item>
          <el-form-item label="QoS">
            <el-input v-model.number="protoEditor.mqtt.qos" type="number" />
          </el-form-item>
        </el-form>
      </template>
      <template v-else-if="form.protocolType === 'tcp'">
        <el-form label-width="120px">
          <el-form-item label="Host">
            <el-input v-model="protoEditor.tcp.host" />
          </el-form-item>
          <el-form-item label="Port">
            <el-input v-model.number="protoEditor.tcp.port" type="number" />
          </el-form-item>
          <el-form-item label="超时(ms)">
            <el-input v-model.number="protoEditor.tcp.timeoutMs" type="number" />
          </el-form-item>
        </el-form>
      </template>
      <template v-else-if="form.protocolType === 'modbus'">
        <el-form label-width="120px">
          <el-form-item label="类型">
            <el-select v-model="protoEditor.modbus.type" style="width:100%">
              <el-option label="TCP" value="tcp" />
              <el-option label="RTU" value="rtu" />
            </el-select>
          </el-form-item>
          <template v-if="protoEditor.modbus.type === 'tcp'">
            <el-form-item label="Host">
              <el-input v-model="protoEditor.modbus.host" />
            </el-form-item>
            <el-form-item label="Port">
              <el-input v-model.number="protoEditor.modbus.port" type="number" />
            </el-form-item>
            <el-form-item label="超时(ms)">
              <el-input v-model.number="protoEditor.modbus.timeoutMs" type="number" />
            </el-form-item>
          </template>
          <template v-else>
            <el-form-item label="串口名">
              <el-input v-model="protoEditor.modbus.portName" placeholder="COM1 或 /dev/ttyS0" />
            </el-form-item>
            <el-form-item label="波特率">
              <el-input v-model.number="protoEditor.modbus.baudRate" type="number" />
            </el-form-item>
            <el-form-item label="数据位">
              <el-input v-model.number="protoEditor.modbus.dataBits" type="number" />
            </el-form-item>
            <el-form-item label="停止位">
              <el-input v-model.number="protoEditor.modbus.stopBits" type="number" />
            </el-form-item>
            <el-form-item label="校验">
              <el-input v-model.number="protoEditor.modbus.parity" type="number" />
            </el-form-item>
            <el-form-item label="超时(ms)">
              <el-input v-model.number="protoEditor.modbus.timeoutMs" type="number" />
            </el-form-item>
          </template>

          <!-- 新增：点位配置表（与设备侧一致） -->
          <el-divider>点位配置 (points)</el-divider>
          <div>
            <el-button type="primary" link @click="addProductModbusPoint">新增点位</el-button>
          </div>
          <el-table :data="protoEditor.modbus.points" size="small" border stripe style="margin-top:8px">
            <el-table-column label="code" min-width="140">
              <template #default="{ row }">
                <el-input v-model="row.code" placeholder="如 temperature" />
              </template>
            </el-table-column>
            <el-table-column label="function" width="140">
              <template #default="{ row }">
                <el-select v-model="row.function" style="width:120px">
                  <el-option label="holding" value="holding" />
                </el-select>
              </template>
            </el-table-column>
            <el-table-column label="slaveId" width="120">
              <template #default="{ row }">
                <el-input-number v-model="row.slaveId" :min="0" :step="1" />
              </template>
            </el-table-column>
            <el-table-column label="offset" width="120">
              <template #default="{ row }">
                <el-input-number v-model="row.offset" :min="0" :step="1" />
              </template>
            </el-table-column>
            <el-table-column label="quantity" width="120">
              <template #default="{ row }">
                <el-input-number v-model="row.quantity" :min="1" :step="1" />
              </template>
            </el-table-column>
            <el-table-column label="periodSec" width="140">
              <template #default="{ row }">
                <el-input-number v-model="row.periodSec" :min="1" :step="1" />
              </template>
            </el-table-column>
            <el-table-column label="操作" width="100">
              <template #default="{ $index }">
                <el-button type="danger" link @click="removeProductModbusPoint($index)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-form>
      </template>
      <template v-else-if="form.protocolType === 'http'">
        <el-form label-width="120px">
          <el-form-item label="Base URL">
            <el-input v-model="protoEditor.http.baseUrl" />
          </el-form-item>
          <el-form-item label="Path">
            <el-input v-model="protoEditor.http.path" />
          </el-form-item>
          <el-form-item label="Method">
            <el-input v-model="protoEditor.http.method" placeholder="GET/POST..." />
          </el-form-item>
        </el-form>
      </template>
      <template v-else-if="form.protocolType === 'coap'">
        <el-form label-width="120px">
          <el-form-item label="Host">
            <el-input v-model="protoEditor.coap.host" />
          </el-form-item>
          <el-form-item label="Port">
            <el-input v-model.number="protoEditor.coap.port" type="number" />
          </el-form-item>
          <el-form-item label="Path">
            <el-input v-model="protoEditor.coap.path" />
          </el-form-item>
        </el-form>
      </template>
      <template #footer>
        <el-button @click="protoEditor.visible = false">取消</el-button>
        <el-button type="primary" @click="applyProtoEditor">确定</el-button>
      </template>
    </el-dialog>

    <!-- 产品详情对话框 -->
    <el-dialog title="产品详情" v-model="detailDialog.visible" width="800px" append-to-body>
      <el-descriptions :column="2" border>
        <el-descriptions-item label="产品名称">{{ detailData.productName }}</el-descriptions-item>
        <el-descriptions-item label="产品编码">{{ detailData.productCode }}</el-descriptions-item>
        <el-descriptions-item label="产品分类">{{ detailData.categoryName }}</el-descriptions-item>
        <el-descriptions-item label="设备类型">
          <dict-tag :options="deviceTypeOptions" :value="detailData.deviceType" />
        </el-descriptions-item>
        <el-descriptions-item label="产品型号">{{ detailData.productModel }}</el-descriptions-item>
        <el-descriptions-item label="产品品牌">{{ detailData.brand }}</el-descriptions-item>
        <el-descriptions-item label="产品规格">{{ detailData.specification }}</el-descriptions-item>
        <el-descriptions-item label="通信协议">{{ detailData.protocolType }}</el-descriptions-item>
        <el-descriptions-item label="绑定规则ID">{{ detailData.flowId || '-' }}</el-descriptions-item>
        <el-descriptions-item label="数据格式">{{ detailData.dataFormat }}</el-descriptions-item>
        <el-descriptions-item label="工作电压">{{ detailData.workingVoltage }}</el-descriptions-item>
        <el-descriptions-item label="工作温度">{{ detailData.workingTemperature }}</el-descriptions-item>
        <el-descriptions-item label="防护等级">{{ detailData.protectionLevel }}</el-descriptions-item>
        <el-descriptions-item label="产品价格">¥{{ detailData.price }}</el-descriptions-item>
        <el-descriptions-item label="供应商">{{ detailData.supplier }}</el-descriptions-item>
        <el-descriptions-item label="供应商联系方式">{{ detailData.supplierContact }}</el-descriptions-item>
        <el-descriptions-item label="产品状态">
          <el-tag v-if="detailData.status === '0'" type="success">正常</el-tag>
          <el-tag v-else-if="detailData.status === '1'" type="danger">停用</el-tag>
          <span v-else>-</span>
        </el-descriptions-item>
        <el-descriptions-item label="创建时间">{{ parseTime(detailData.createTime) }}</el-descriptions-item>
        <el-descriptions-item label="产品描述" :span="2">{{ detailData.description }}</el-descriptions-item>
        <el-descriptions-item label="技术参数" :span="2">{{ detailData.technicalParams }}</el-descriptions-item>
      </el-descriptions>
    </el-dialog>
  <!-- 规则选择对话框 -->
  <el-dialog v-model="flowSelector.visible" title="选择规则" width="800px" append-to-body>
    <div style="display:flex; gap:8px; align-items:center; margin-bottom:12px">
      <el-input v-model="flowQuery.flowName" placeholder="规则名称" clearable style="width:200px" />
      <el-button type="primary" @click="loadFlows">查询</el-button>
      <el-button @click="resetFlowQuery">重置</el-button>
    </div>
    
    <el-table 
      :data="flowRows" 
      border 
      stripe
      style="cursor: pointer"
    >
      <el-table-column prop="flowName" label="规则名称" min-width="200" />
      <el-table-column prop="flowDescription" label="描述" min-width="260" />
      <el-table-column prop="isActive" label="是否激活" width="100">
        <template #default="{ row }">
          <el-tag :type="row.isActive ? 'success' : 'info'">{{ row.isActive ? '是' : '否' }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="80">
        <template #default="{ row }">
          <el-button size="small" type="primary" @click="selectFlow(row)">选择</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <div style="margin-top:12px; text-align:right">
      <el-pagination
        background
        layout="total, sizes, prev, pager, next, jumper"
        :page-sizes="[10,20,50,100]"
        v-model:current-page="flowQuery.pageNum"
        v-model:page-size="flowQuery.pageSize"
        :total="flowTotal"
        @size-change="loadFlows"
        @current-change="loadFlows"
      />
    </div>
    
    <template #footer>
      <el-button @click="flowSelector.visible = false">取消</el-button>
    </template>
  </el-dialog>
</div>
</template>

<script setup name="Product" lang="ts">
import { ref, reactive, computed, nextTick, onMounted, getCurrentInstance, type ComponentInternalInstance, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { listProduct, getProduct, delProduct, addProduct, updateProduct } from '@/api/iot/product'
import type { IotProductVO, IotProductQuery, IotProductForm } from '@/api/iot/product/types'
import { listCategory } from '@/api/iot/category'
import { getDicts } from '@/api/system/dict/data'
import { handleTree } from '@/utils/ruoyi'
import { getNodeRedFlows } from '@/api/iot/nodered'
import { getNodeRedFlow } from '@/api/iot/nodered'
import { parseTime } from '@/utils/ruoyi'
import { Search } from '@element-plus/icons-vue'

const { proxy } = getCurrentInstance() as ComponentInternalInstance
const modal = (proxy as any)?.$modal

// 列表与查询状态
const productList = ref<IotProductVO[]>([])
const buttonLoading = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref<Array<string | number>>([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)

const queryFormRef = ref()
const productFormRef = ref()

const dialog = reactive({ visible: false, title: '' })
const detailDialog = reactive({ visible: false, title: '' })

// 新增：表单页签
const productFormTab = ref<'basic' | 'protocol'>('basic')

// 下拉与字典
const categoryOptions = ref<any[]>([])
const deviceTypeOptions = ref<any[]>([])

// 表单
const initFormData: IotProductForm = {
  productId: undefined,
  productName: '',
  productCode: '',
  categoryId: undefined,
  deviceType: '',
  productModel: '',
  brand: '',
  specification: '',
  productImage: '',
  description: '',
  technicalParams: '',
  protocolType: '',
  flowId: undefined,
  dataFormat: '',
  workingVoltage: '',
  workingTemperature: '',
  protectionLevel: '',
  price: undefined,
  supplier: '',
  supplierContact: '',
  status: '0'
}

const form = ref<IotProductForm>({ ...initFormData })
const detailData = ref<any>({})

const queryParams = reactive<any>({
  pageNum: 1,
  pageSize: 10,
  productName: '',
  productCode: '',
  categoryId: undefined,
  productModel: '',
  brand: '',
  protocolType: '',
  supplier: '',
  status: '',
  deviceType: ''
})

const rules = reactive<any>({
  productName: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }],
  productCode: [{ required: true, message: '产品编码不能为空', trigger: 'blur' }],
  categoryId: [{ required: true, message: '产品分类不能为空', trigger: 'change' }],
  deviceType: [{ required: true, message: '设备类型不能为空', trigger: 'change' }]
})

// 规则选择显示名
const flowOptions = ref<any[]>([])
const flowRows = ref<any[]>([])
const flowNameMap = reactive<Record<string, string>>({})

function sameId(a: any, b: any) {
  if (a == null || b == null) return false
  return String(a) === String(b)
}

const selectedFlowName = computed(() => {
  if (!form.value.flowId) return ''
  const key = String(form.value.flowId)
  if (flowNameMap[key]) return flowNameMap[key]
  const f = flowRows.value.find(it => sameId(it.flowId, form.value.flowId)) || flowOptions.value.find(it => sameId(it.flowId, form.value.flowId))
  return f ? f.flowName : ''
})

async function ensureFlowName(flowId?: number) {
  if (!flowId) return
  const key = String(flowId)
  const exists = flowRows.value.some(it => sameId(it.flowId, flowId)) || flowOptions.value.some(it => sameId(it.flowId, flowId))
  if (flowNameMap[key]) return
  try {
    const res: any = await getNodeRedFlow(String(flowId))
    const flow = res?.data?.data || res?.data || res
    if (flow && (sameId(flow.flowId, flowId) || flow.flowId != null)) {
      flowOptions.value = [...flowOptions.value, flow]
      if (flow.flowName) flowNameMap[key] = flow.flowName
    }
  } catch {}
}

async function loadFlowOptions() {
  try {
    const res = await getNodeRedFlows({})
    const data = res?.data?.records || res?.data || []
    const arr = Array.isArray(data) ? data : []
    flowOptions.value = arr
    // 预填充名称缓存
    for (const it of arr) {
      if (it?.flowId != null && it?.flowName) flowNameMap[String(it.flowId)] = it.flowName
    }
  } catch {
    flowOptions.value = []
  }
}

/** 查询产品列表 */
const getList = async () => {
  loading.value = true
  try {
    const res: any = await listProduct(queryParams as any)
    let data: any[] = []
    let totalCount = 0
    if (res?.data?.rows) {
      data = res.data.rows
      totalCount = res.data.total || 0
    } else if (res?.rows) {
      data = res.rows
      totalCount = res.total || 0
    } else if (res?.data?.records) {
      data = res.data.records
      totalCount = res.data.total || 0
    } else if (Array.isArray(res?.data)) {
      data = res.data
      totalCount = data.length
    }
    productList.value = Array.isArray(data) ? data : []
    total.value = totalCount
  } catch (error) {
    productList.value = []
    total.value = 0
  } finally {
    loading.value = false
  }
}

/** 分类树 */
const getCategoryOptions = async () => {
  try {
    const res: any = await listCategory()
    let data: any[] = []
    if (res?.data?.rows) data = res.data.rows
    else if (res?.rows) data = res.rows
    else if (Array.isArray(res?.data)) data = res.data
    else if (Array.isArray(res)) data = res
    categoryOptions.value = handleTree(Array.isArray(data) ? data : [], 'categoryId', 'parentId', 'children')
  } catch {
    categoryOptions.value = []
  }
}

/** 字典：设备类型 */
const loadDeviceTypeDict = async () => {
  try {
    const res = await getDicts('sys_device_type')
    if (Array.isArray(res?.data)) {
      deviceTypeOptions.value = res.data.map((it: any) => ({ value: it.dictValue, label: it.dictLabel }))
    } else {
      deviceTypeOptions.value = []
    }
  } catch {
    deviceTypeOptions.value = []
  }
}

/** 表单重置 */
const reset = () => {
  form.value = JSON.parse(JSON.stringify(initFormData))
  productFormTab.value = 'basic'
  nextTick(() => {
    productFormRef.value?.resetFields()
  })
}

/** 搜索与重置 */
const handleQuery = () => { queryParams.pageNum = 1; getList() }
const resetQuery = () => { queryFormRef.value?.resetFields(); handleQuery() }

/** 新增 */
const handleAdd = async () => {
  reset()
  await Promise.all([getCategoryOptions(), loadDeviceTypeDict(), loadFlowOptions()])
  dialog.visible = true
  dialog.title = '添加产品'
}

/** 修改 */
const handleUpdate = async (row?: IotProductVO) => {
  reset()
  await Promise.all([getCategoryOptions(), loadDeviceTypeDict(), loadFlowOptions()])
  const productId = row?.productId || ids.value[0]
  const res = await getProduct(productId as any)
  const productData: any = { ...res.data }
  if (productData.price && typeof productData.price === 'string') productData.price = parseFloat(productData.price)
  Object.assign(form.value, productData)
  await ensureFlowName(form.value.flowId as any)
  dialog.visible = true
  dialog.title = '修改产品'
}

/** 查看 */
const handleView = async (row: IotProductVO) => {
  const res = await getProduct(row.productId as any)
  detailData.value = res.data
  detailDialog.visible = true
}

/** 提交 */
const submitForm = () => {
  const submitData: any = { ...form.value }
  if (submitData.price && typeof submitData.price === 'string') submitData.price = parseFloat(submitData.price)
  productFormRef.value?.validate(async (valid: boolean) => {
    if (!valid) return
    buttonLoading.value = true
    try {
      if (submitData.productId != null) {
        await updateProduct(submitData)
        modal?.msgSuccess ? modal.msgSuccess('修改成功') : ElMessage.success('修改成功')
      } else {
        await addProduct(submitData)
        modal?.msgSuccess ? modal.msgSuccess('新增成功') : ElMessage.success('新增成功')
      }
      dialog.visible = false
      await getList()
    } finally {
      buttonLoading.value = false
    }
  })
}

/** 删除 */
const handleDelete = async (row?: IotProductVO) => {
  const productIds = (row?.productId as any) || ids.value
  await modal?.confirm?.('是否确认删除产品编号为"' + productIds + '"的数据项？')
  await delProduct(productIds)
  await getList()
  modal?.msgSuccess ? modal.msgSuccess('删除成功') : ElMessage.success('删除成功')
}

/** 多选 */
const handleSelectionChange = (selection: IotProductVO[]) => {
  ids.value = selection.map(item => item.productId as any)
  single.value = selection.length !== 1
  multiple.value = !selection.length
}

/** 关闭/取消 */
const closeDialog = () => { dialog.visible = false; reset() }
const cancel = () => { dialog.visible = false; reset() }

// 规则选择对话框状态与方法
const flowSelector = reactive<{ visible: boolean }>({ visible: false })
const flowQuery = reactive<{ flowName: string; pageNum: number; pageSize: number }>({ flowName: '', pageNum: 1, pageSize: 10 })
const flowTotal = ref(0)

function openFlowSelector() { flowSelector.visible = true; loadFlows() }
function resetFlowQuery() { flowQuery.flowName = ''; flowQuery.pageNum = 1; flowQuery.pageSize = 10; loadFlows() }

async function loadFlows() {
  try {
    const params: any = { pageNum: flowQuery.pageNum, pageSize: flowQuery.pageSize }
    if (flowQuery.flowName) params.flowName = flowQuery.flowName
    const res = await getNodeRedFlows(params)
    const data = res?.data?.records || []
    const totalCount = res?.data?.total || 0
    flowRows.value = Array.isArray(data) ? data : []
    flowTotal.value = totalCount
  } catch {
    flowRows.value = []
    flowTotal.value = 0
  }
}

function selectFlow(row: any) {
  form.value.flowId = row.flowId
  if (row?.flowId != null && row?.flowName) flowNameMap[String(row.flowId)] = row.flowName
  flowSelector.visible = false
  modal?.msgSuccess ? modal.msgSuccess(`已选择规则：${row.flowName}`) : ElMessage.success(`已选择规则：${row.flowName}`)
}

// 协议参数编辑对话框状态与方法
const protoEditor = reactive({
  visible: false,
  mqtt: {
    brokerUrl: '',
    clientId: '',
    username: '',
    password: '',
    publishTopic: '',
    subscribeTopic: '',
    qos: 0
  },
  tcp: {
    host: '',
    port: 0,
    timeoutMs: 0
  },
  modbus: {
    type: 'tcp',
    host: '',
    port: 0,
    portName: '',
    baudRate: 0,
    dataBits: 0,
    stopBits: 0,
    parity: 0,
    timeoutMs: 0,
    points: [] as any[]
  },
  http: {
    baseUrl: '',
    path: '',
    method: ''
  },
  coap: {
    host: '',
    port: 0,
    path: ''
  }
})

// 各协议默认值
const defaultProtocolConfig: Record<string, any> = {
  mqtt: {
    brokerUrl: 'mqtt://127.0.0.1:1883',
    clientId: 'product-001',
    username: '',
    password: '',
    publishTopic: 'devices/${deviceCode}/down',
    subscribeTopic: 'devices/${deviceCode}/up',
    qos: 0
  },
  tcp: {
    host: '127.0.0.1',
    port: 502,
    timeoutMs: 2000
  },
  'tcp-server': {
    port: 9999,
    bufferSize: 1024,
    dataFormat: 'text'
  },
  'udp-server': {
    port: 9998,
    bufferSize: 1024,
    dataFormat: 'text'
  },
  modbus: {
    type: 'tcp',
    host: '127.0.0.1',
    port: 502,
    timeoutMs: 2000,
    portName: 'COM1',
    baudRate: 9600,
    dataBits: 8,
    stopBits: 1,
    parity: 0,
    points: []
  },
  http: {
    baseUrl: 'http://127.0.0.1:8080',
    path: '/api/data',
    method: 'POST'
  },
  coap: {
    host: '127.0.0.1',
    port: 5683,
    path: '/resource'
  }
}

const protocolJsonPlaceholder = computed(() => {
  if (!form.value.protocolType) return ''
  if (form.value.protocolType === 'mqtt') {
    return '示例: {"brokerUrl":"mqtt://127.0.0.1:1883","clientId":"myClient","username":"user","password":"pass","publishTopic":"topic/test","subscribeTopic":"topic/test","qos":0}'
  } else if (form.value.protocolType === 'tcp') {
    return '示例: {"host":"127.0.0.1","port":502,"timeoutMs":2000}'
  } else if (form.value.protocolType === 'tcp-server') {
    return '示例: {"port":9999,"bufferSize":1024,"dataFormat":"text"}'
  } else if (form.value.protocolType === 'udp-server') {
    return '示例: {"port":9998,"bufferSize":1024,"dataFormat":"text"}'
  } else if (form.value.protocolType === 'modbus') {
    return '示例: {"type":"tcp","host":"127.0.0.1","port":502,"timeoutMs":2000}'
  } else if (form.value.protocolType === 'http') {
    return '示例: {"baseUrl":"http://localhost:8080","path":"/api/data","method":"GET"}'
  } else if (form.value.protocolType === 'coap') {
    return '示例: {"host":"127.0.0.1","port":5683,"path":"/resource"}'
  }
  return ''
})

function openProtoEditor() {
  if (form.value.protocolType === 'mqtt') {
    protoEditor.mqtt = { ...defaultProtocolConfig.mqtt, ...(form.value.protocolConfig ? JSON.parse(form.value.protocolConfig) : {}) }
  } else if (form.value.protocolType === 'tcp') {
    protoEditor.tcp = { ...defaultProtocolConfig.tcp, ...(form.value.protocolConfig ? JSON.parse(form.value.protocolConfig) : {}) }
  } else if (form.value.protocolType === 'modbus') {
    const obj = form.value.protocolConfig ? JSON.parse(form.value.protocolConfig) : {}
    const parsed = { ...defaultProtocolConfig.modbus, ...obj }
    parsed.points = Array.isArray(obj.points) ? obj.points : []
    protoEditor.modbus = parsed
  } else if (form.value.protocolType === 'http') {
    protoEditor.http = { ...defaultProtocolConfig.http, ...(form.value.protocolConfig ? JSON.parse(form.value.protocolConfig) : {}) }
  } else if (form.value.protocolType === 'coap') {
    protoEditor.coap = { ...defaultProtocolConfig.coap, ...(form.value.protocolConfig ? JSON.parse(form.value.protocolConfig) : {}) }
  }
  protoEditor.visible = true
}

function addProductModbusPoint() {
  protoEditor.modbus.points.push({ code: '', function: 'holding', slaveId: 1, offset: 0, quantity: 1, periodSec: 5 })
}
function removeProductModbusPoint(idx: number) {
  protoEditor.modbus.points.splice(idx, 1)
}

function applyProtoEditor() {
  if (form.value.protocolType === 'mqtt') {
    form.value.protocolConfig = JSON.stringify(protoEditor.mqtt)
  } else if (form.value.protocolType === 'tcp') {
    form.value.protocolConfig = JSON.stringify(protoEditor.tcp)
  } else if (form.value.protocolType === 'modbus') {
    if (!protoEditor.modbus.points || protoEditor.modbus.points.length === 0) {
      ElMessage.error('请至少配置一个 Modbus 点位')
      return
    }
    form.value.protocolConfig = JSON.stringify({
      type: protoEditor.modbus.type,
      host: protoEditor.modbus.host,
      port: protoEditor.modbus.port,
      timeoutMs: protoEditor.modbus.timeoutMs,
      portName: protoEditor.modbus.portName,
      baudRate: protoEditor.modbus.baudRate,
      dataBits: protoEditor.modbus.dataBits,
      stopBits: protoEditor.modbus.stopBits,
      parity: protoEditor.modbus.parity,
      points: protoEditor.modbus.points
    })
  } else if (form.value.protocolType === 'http') {
    form.value.protocolConfig = JSON.stringify(protoEditor.http)
  } else if (form.value.protocolType === 'coap') {
    form.value.protocolConfig = JSON.stringify(protoEditor.coap)
  }
  protoEditor.visible = false
}

onMounted(() => {
  getList()
  getCategoryOptions()
  loadDeviceTypeDict()
  loadFlowOptions()
})

// 监听 flowId 变化，确保名称可显示
watch(() => form.value.flowId, (val) => { ensureFlowName(val as any) })

// 当选择协议且当前没有JSON配置时，预填默认值
watch(() => form.value.protocolType, (type) => {
  if (!type) return
  if (!form.value.protocolConfig || form.value.protocolConfig.trim() === '') {
    const def = defaultProtocolConfig[type]
    if (def) form.value.protocolConfig = JSON.stringify(def)
  }
})
</script>

<style scoped>
.search-container {
  margin-bottom: 20px;
}
</style>